<?php


/**
 * kuoqi核心信息
 */
namespace Kuoqi{

    /**
     * Class Params
     * @package Kuoqi
     * User kuoqi
     * Datetime 2022/2/26 11:22
     * Remark 系统参数模块
     */
    class Params{

        /**
         * User kuoqi
         * Datetime 2022/2/26 19:48
         * Remark init params
         */
        static function __initialize(){
            //强制定义安全字段，防止文件在服务器被异常执行
            defined('SAFE_CODE')||define('SAFE_CODE',true);
            Error::process('params init');
            self::$APP_CONFIG = new \stdClass();
            self::$ROOT = dirname(__FILE__);//ROOT系统根目录的路径信息
            self::$APP_ROOT = dirname(dirname(__FILE__));//ROOT系统根目录的路径信息
            //home自动居于app_root的web下
            //self::$HOME = dirname(dirname(__FILE__)).'/web';//WEB_ROOT系统根目录的路径信息

            self::$METHOD = isset($_SERVER['REQUEST_METHOD'])?$_SERVER['REQUEST_METHOD']:'get';

            self::$HOST = isset($_SERVER['HTTP_HOST'])?$_SERVER['HTTP_HOST']:'';
            self::$PHP_MODE = self::$CODE_MODE_WEB;
            //去除cli模式的自动化，这个以后再考虑
            //todo--去除cli模式的自动化，这个以后再考虑
            if(strtolower(PHP_SAPI)=='cli'){
                self::$PHP_MODE = self::$CODE_MODE_CLI;
                //配置应用的app目录
                //defined('APP_ROOT')||define('APP_ROOT',$_SERVER["LOCALAPPDATA"].DS.'Kuoqi');
                //尝试配置APP_ROOT的相关信息
                if(strtoupper(substr(PHP_OS,0,3))=='WIN'){
                    //defined('APP_ROOT')||define('APP_ROOT',$_SERVER['APP_ROOT']);
                }else{
                    //defined('APP_ROOT')||define('APP_ROOT',$_SERVER['PWD']);
                }
            }else{

            }

        }

        //当前版本信息
        static $VERSION = 'v1.00.03';

        /**
         * @var array
         * User kuoqi
         * Datetime 2022/2/26 11:43
         * Remark 流程日志信息，每一个流程就简单的用一句话实现即可
         */
        static $PROCESS_LOGS = array();

        /**
         * @var array
         * User kuoqi
         * Datetime 2022/2/27 9:59
         * Remark get信息输入对象信息
         */
        static $INPUT_GETS = array();

        /**
         * @var array
         * User kuoqi
         * Datetime 2022/2/27 9:59
         * Remark post输入数据信息
         */
        static $INPUT_POSTS = array();

        /**
         * 使用json的方式输入数据信息
         * @var array
         */
        static $INPUT_JSONS = array();

        /**
         * Error模式
         * @var bool
         * User kuoqi
         * Datetime 2022/2/26 19:55
         * Remark
         */
        static $DEBUG = false;

        /**
         * 用户debug模式
         * @var bool
         * User kuoqi
         * Datetime 2022/2/26 19:55
         * Remark
         */
        static $APP_DEBUG = true;

        /**
         * @var string
         * User kuoqi
         * Datetime 2022/2/27 0:02
         * Remark 系统根目录
         */
        static $ROOT = '';

        /**
         * @var string
         * User kuoqi
         * Datetime 2022/2/27 0:02
         * Remark 应用根目录
         */
        static $APP_ROOT = '';

        /**
         * @var string
         * User kuoqi
         * Datetime 2022/2/27 0:02
         * Remark 应用目录
         */
        static $HOME = '';

        /**
         * @var string
         * User kuoqi
         * Datetime 2022/2/27 0:02
         * Remark 请求方式
         */
        static $METHOD = '';

        /**
         * @var null
         * User kuoqi
         * Datetime 2022/2/26 19:55
         * Remark 用户配置基础数据信息
         */
        static $APP_CONFIG = null;

        /**
         * @var string
         * User kuoqi
         * Datetime 2022/2/26 20:27
         * Remark 路由转换基础参数
         */
        static $RL = '\\';

        /**
         * @var string
         * User kuoqi
         * Datetime 2022/2/26 21:30
         * Remark  文件路径信息
         */
        static $DS = DIRECTORY_SEPARATOR;

        /**
         * @var string
         * User kuoqi
         * Datetime 2022/3/1 11:41
         * Remark 斜杠
         */
        static $LL = '/';

        /**
         * @var string 获取app的路径信息
         */
        static $APP_PATH = 'application';

        /**
         * @var string
         * User kuoqi
         * Datetime 2022/2/27 0:09
         * Remark 默认的模型层
         */
        static $DEFAULT_MOD = 'Index';

        /**
         * @var string
         * User kuoqi
         * Datetime 2022/2/27 0:10
         * Remark 默认的控制器层
         */
        static $DEFAULT_CTL = 'Index';

        /**
         * @var string
         * User kuoqi
         * Datetime 2022/2/27 0:10
         * Remark 默认动作层
         */
        static $DEFAULT_ACT = 'Index';

        /**
         * @var string
         * User kuoqi
         * Datetime 2022/2/27 0:16
         * Remark 系统主入口信息
         */
        static $INDEX = '/index.php';

        /**
         * @var string 入口伪装或去入口伪装表达式
         * User kuoqi
         * Datetime 2022/2/27 9:08
         * Remark
         */
        static $INDEX_FEIGNZZ = '/(\.php|\.html|\.js|\.css)\/?/';//sss

        /**
         * @var int 路由模式 1:为展示常用，不做域名重定向,2:为做域名重定向，3：使用参数模式
         * User kuoqi
         * Datetime 2022/2/27 0:15
         * Remark 2已调试
         */
        static $INDEX_PHPINFO = 1;

        /**
         * @var string
         * User kuoqi
         * Datetime 2022/2/28 15:42
         * Remark 模板文件结尾名
         */
        static $VIEW_EXT = '.html';

        /**
         * @var string
         * User kuoqi
         * Datetime 2022/2/28 16:44
         * Remark 缓存路径信息,缓存模块的所有文件目录信息
         */
        static $RUNTIME_PATH = 'runtime';

        /**
         * @var string
         * User kuoqi
         * Datetime 2022/2/28 16:47
         * Remark 缓存目录体系
         */
        static $CACHE_PATH = 'cache';

        /**
         * 域名地址信息，包含端口的那种喔
         * @var string
         * User kuoqi
         * Datetime 2022/4/14 12:41
         * Remark
         */
        static $HOST = '';

        /**
         * @var string
         * User kuoqi
         * Datetime 2022/2/28 16:48
         * Remark 模型路径信息
         */
        static $TEMPLATE_PATH = 'template';
        /**
         * 日志模块的路径,理论上的路径为{APP_ROOT}/runtime/logs
         * vbase
         * @var string
         */
        static $LOG_ROOT = '{@APP}/runtime/logs';

        static $PHP_MODE = 0;//基础的php模式
        static $CODE_MODE_WEB = 0;//使用web模式
        static $CODE_MODE_CLI = 1;//使用cli模式
        static $PHP_VERSION = PHP_VERSION;//php版本号信息

        /**
         * 日志模块的缓存文件列表
         * @var array
         */
        static $LOG_DATA = array();


    }


    /**
     * 异常处理模块-为了不跟php默认冲突，使用debug替换原有的Exception
     * Class Debug
     * @package Kuoqi
     */
    class Error extends \Exception {
        /**
         * @var bool
         * User kuoqi
         * Datetime 2022/3/1 10:53
         * Remark 是否允许死掉
         */
        static $can_die = true;
        /**
         * @param $message
         * User kuoqi
         * Datetime 2022/2/26 11:45
         * Remark 创建一个流程日志信息
         */
        static function process($message){
            if(Params::$DEBUG){
                Params::$PROCESS_LOGS[] = array('info'=>'process','message'=>$message);
            }
        }
        /**
         * @return string
         * User kuoqi
         * Datetime 2022/2/26 12:23
         * Remark 流程异常显示部分
         */
        static function processShow(){
            $stream = '<p style="margin: 0;padding: 0.5em; font-family: Arial,Verdana,sans-serif; font-size: inherit;color: #376a56;"><span style="font-weight: bold;">生命周期</span>:';
            foreach(Params::$PROCESS_LOGS as $item){
                $stream .= ' -> '.$item['message'];
            }
            $stream .= '</p>';
            return $stream;
        }

        /**
         * @param $tips
         * @param $conts
         * User kuoqi
         * Datetime 2022/3/3 13:35
         * Remark warning 部分写入
         */
        static function warning($tips,$conts){
            $debug = debug_backtrace();//获取最后一个数据信息
            //todo--warning.部分写入
        }

        /**
         * 显示错误code的内容信息
         * createby kuoqi at 2022/11/8 9:52
         * @param $code
         */
        static function showErrcode($code){
            $err = new \Kuoqi\Core\Errcode($code);
            $error = new self($err->errmsg());
            $error->quit();
        }

        /**
         * User kuoqi
         * Datetime 2022/3/1 10:52
         * Remark 得到一次忽略错误的机会
         */
        public static function dieOn(){
            self::$can_die = true;
        }

        /**
         * User kuoqi
         * Datetime 2022/3/1 10:52
         * Remark 重置错误节点机会
         */
        public static function dieOff(){
            self::$can_die = false;
        }

        /**
         * @param $stream
         * @return mixed
         * User kuoqi
         * Datetime 2022/2/27 11:39
         * Remark 过滤输出字符串
         */
        static function echofilter($stream){
            $stream = str_replace(array(Params::$ROOT,Params::$APP_ROOT),array('${ROOT}','${APP_ROOT}'),$stream);
            return $stream;
        }

        /**
         * @var string
         * User kuoqi
         * Datetime 2022/3/1 15:41
         * Remark 被注入的错误信息
         */
        public $trace_stream = '';

        /**
         * 初始化 ,异常处理的基础包信息，其他情况请勿调用，除了需要显示异常的地方，因为发现，静态使用也会调用这个初始化方法
         * Error constructor.
         * @param string $message
         */
        public function __construct($message = "")
        {
            $message = print_r($message,true);
            parent::__construct(print_r($message,true));
        }
        /**
         * 获取异常数据信息,获取当前异常信息的基础处理
         * @return string
         * User kuoqi
         * Datetime 2022/2/26 20:33
         * Remark
         */
        public function getErrornow(){
            //基础异常信息
            $stream = '<div style="font-family: Arial,Verdana,sans-serif; font-size: inherit; background-color: #4a5a80; margin: 0 0 0 0; padding: 0.5em 0.75em;font-weight: bold;color:#ffffff;">'.$this->getMessage().'</div>';
            //基础页面信息
            $stream .= sprintf('<p style="font-family: Arial,Verdana,sans-serif; font-size: inherit; margin: 0.5em; font-weight: 600;color: #376a56;">errmsg file: %s  on line %s</p>',
                self::echofilter($this->getFile()),
                $this->getLine()
                );
            return $stream;
        }

        /**
         * @param $code
         * User kuoqi
         * Datetime 2022/3/1 15:31
         * Remark 配置code
         */
        public function setCode($code){
            $this->code = $code;
        }

        /**
         * @param $file
         * User kuoqi
         * Datetime 2022/3/1 15:31
         * Remark 配置file
         */
        public function setFile($file){
            $this->file = $file;
        }

        /**
         * @param $line
         * User kuoqi
         * Datetime 2022/3/1 15:31
         * Remark 配置line
         */
        public function setLine($line){
            $this->line = $line;
        }

        /**
         * @param $stream
         * User kuoqi
         * Datetime 2022/3/1 15:42
         * Remark 注入错误信息
         */
        public function setTraceStream($stream){
            $this->trace_stream = $stream;
        }

        /**
         * @return string
         * User kuoqi
         * Datetime 2022/3/1 15:43
         * Remark 获取调试信息
         */
        public function getTraceStream(){
            if($this->trace_stream){
                return $this->trace_stream;
            }else{
                return $this->getTraceAsString();
            }
        }


        //自动显示已加载的路由信息
        final function _autoRoutes(){
            $stream = '';
            foreach(\Kuoqi\Route::$AUTOLOAD_ROUTE_LIST as $item){
                $stream .=  sprintf('<pre style="margin: 0;padding: 5px 15px 5px 30px; font-family: Arial,Verdana,sans-serif; font-size: inherit;color:#666666">%s</pre>',$item);
            }
            echo sprintf('<details style="font-size: 0.85em;"><summary style="margin: 0;padding: 5px 15px; font-family: Arial,Verdana,sans-serif; font-size: inherit;color:#666666">路由信息</summary>%s</details>',$stream);
        }
        //自动显示已加载的文件列表信息
        final function _autoFiles(){
            $stream = '';
            foreach(\Kuoqi\Route::$AUTOLOAD_FILE_LIST as $item){
                $stream .=  sprintf('<pre style="margin: 0;padding: 5px 15px 5px 30px; font-family: Arial,Verdana,sans-serif; font-size: inherit;color:#666666">%s</pre>',$item);
            }
            echo sprintf('<details style="font-size: 0.85em;"><summary style="margin: 0;padding: 5px 15px; font-family: Arial,Verdana,sans-serif; font-size: inherit;color:#666666">加载文件信息</summary>%s</details>',$stream);
        }

        /**
         * cli模式下的信息返回
         */
        final function quit_cli(){
            @header('Content-Type:text/html;charset=UTF-8');
            echo $this->getMessage().PHP_EOL;
            echo sprintf('errmsg file: %s  on line %s',
                self::echofilter($this->getFile()),
                $this->getLine()
            ).PHP_EOL;
            echo $this->getTraceAsString().PHP_EOL;
        }

        /**
         * 展示信息然后死去
         * User kuoqi
         * Datetime 2022/4/28 16:06
         * Remark
         */
        final function quit_debug(){
            @header('Content-Type:text/html;charset=UTF-8');
            echo '<meta http-equiv="Content-Type" content="text/html; CHARSET=utf-8">';
            echo '<meta name="viewport" content="initial-scale=1, width=device-width, maximum-scale=1, user-scalable=no">';
            echo '<style>body{ margin: 0;padding: 0;background-color: #f2efe7;}</style>';
            echo $this->getErrornow();//获取当前异常信息

            echo sprintf('<pre style="margin: 0;padding: 5px 15px; font-family: Arial,Verdana,sans-serif; font-size: inherit;color:#666666">%s</pre>',self::echofilter($this->getTraceStream()));

            echo '';
            //这个是致死的进程
            echo self::processShow();
            //如果是debug模式，展示app_root与root数据，这两个很关键
            //展示路由信息
            echo self::_autoRoutes();//显示已自动加载的路由列表
            echo self::_autoFiles();//显示已自动加载的文件列表
            echo '<p style="margin: 0;padding: 5px 15px; font-family: Arial,Verdana,sans-serif; font-size: inherit;font-size: small;color: #888888;">ROOT->'.Params::$ROOT.'</p>';
            echo '<p style="margin: 0;padding: 5px 15px; font-family: Arial,Verdana,sans-serif; font-size: inherit;font-size: small;color: #888888;">APP_ROOT->'.Params::$APP_ROOT.'</p>';
            echo '<p style="margin: 0;padding: 5px 15px; font-family: Arial,Verdana,sans-serif; font-size: inherit;font-size: small;color: #888888;">HOST->'.Params::$HOST.'</p>';

            //slog
            echo '<p style="margin: 0;padding: 5px 15px; font-family: Arial,Verdana,sans-serif; font-size: inherit;font-size: small;">version:'.Params::$VERSION.'</p>';
            echo '<p style="margin: 0;padding: 5px 15px; font-family: Arial,Verdana,sans-serif; font-size: inherit;font-size: small;">KuoqiPHP-oop -->{PHP依旧是介绍最好的语言}</p>';
            //kill进程
        }
        /**
         * 根据错误模板的死去 这种是没有系统异常的情况下才能使用的那种喔
         * User kuoqi
         * Datetime 2022/4/28 16:16
         * Remark
         */
        final function quit_template(){
            //判断是否有模板内容
            //模板文件不存在
            echo '<h1 style="text-align: center;margin: 0.67em;">404 Not Found</h1>';
            echo '<hr />';
            echo '<p style="text-align: center;">KuoqiPHP '.Params::$VERSION.'</p>';
        }

        /**
         * 主动输出相关数据并结束
         */
        final function quit_active(){
            echo '<h1 style="text-align: center;margin: 0.67em;">'.$this->message.'</h1>';
            echo '<hr />';
            echo '<p style="text-align: center;">KuoqiPHP '.Params::$VERSION.'</p>';
            die();
        }

        public function quit(){
            if(strtolower(PHP_SAPI)=='cli'){
                $this->quit_cli();
            }else{
                if(Params::$DEBUG){
                    $this->quit_debug();
                }else{
                    $this->quit_template();
                }
            }
            die();
        }
    }

    /**
     * Class Config
     * @package Kuoqi
     * User kuoqi
     * Datetime 2022/2/26 11:27
     * Remark 参数常规模块
     */
    class Config{

        /**
         * 静态初始化
         * vbase
         * @param array $opts
         */
        static function __initialize($opts = array()){
            require_once(\Kuoqi\Route::str2rootpath('{@ROOT}/function.php'));
            $config = require_once(\Kuoqi\Route::str2rootpath('{@ROOT}/config.php'));
            if(is_array($config)){
                foreach($config as $k=>$v){
                    self::set($k,$v);
                }
            }
            if(is_array($opts)){
                foreach($opts as $k=>$v){
                    self::set($k,$v);
                }
            }
        }

        /**
         * @param $n
         * @param $v
         * @return mixed
         * User kuoqi
         * Datetime 2022/2/26 20:03
         * Remark 配置参数信息
         */
        static function set($n,$v){
            if(isset(Params::$$n)){Params::$$n = $v;}
            return Params::$APP_CONFIG->$n = $v;
        }

        /**
         * @param $n
         * @return null
         * User kuoqi
         * Datetime 2022/2/26 20:03
         * Remark 获取配置参数信息
         */
        static function get($n){
            return isset(Params::$APP_CONFIG->$n)?Params::$APP_CONFIG->$n:(isset(Params::$$n)?Params::$$n:null);
        }

        /**
         * @param $m
         * @param null $v
         * @return null
         * User kuoqi
         * Datetime 2022/2/27 10:04
         * Remark 配置get方式的参数信息
         */
        static function setInputget($m,$v = null){
            if(is_array($m)){
                //如果是数组，则判定为多数据写入
                foreach ($m as $k=>$item) {
                    self::setInputget($k,$item);
                }
            }else{
                //如果不是数组，判定为常规数据写入
                Params::$INPUT_GETS[$m] = $v;
            }
            return null;
        }

        /**
         * @param $m
         * @param null $v
         * @return null
         * User kuoqi
         * Datetime 2022/2/27 10:11
         * Remark 写入post数据信息到数据序列
         */
        static function setInputpost($m,$v = null){
            if(is_array($m)){
                //如果是数组，则判定为多数据写入
                foreach ($m as $k=>$item) {
                    self::setInputpost($k,$item);
                }
            }else{
                //如果不是数组，判定为常规数据写入
                Params::$INPUT_POSTS[$m] = $v;
            }
            return null;
        }
        //使用json字符串的方式传入
        static function setInputjson($m,$v = null){
            if(is_array($m)){
                //如果是数组，则判定为多数据写入
                foreach ($m as $k=>$item) {
                    self::setInputjson($k,$item);
                }
            }else{
                //如果不是数组，判定为常规数据写入
                Params::$INPUT_JSONS[$m] = $v;
            }
            return null;
        }

        /**
         * @return array
         * User kuoqi
         * Datetime 2022/3/1 17:26
         * Remark 获取inputRequest的所有信息
         */
        static function getInputrequest(){
            return array_merge(Params::$INPUT_GETS,Params::$INPUT_POSTS,Params::$INPUT_JSONS);
        }
    }

    /**
     * Class Route
     * @package Kuoqi
     * User kuoqi
     * Datetime 2022/2/26 20:19
     * Remark 路由模块的基础数据信息
     */
    class Route{
        /**
         * 判定是否初始化DNS信息
         * @var bool
         * User kuoqi
         * Datetime 2022/4/27 17:18
         * Remark
         */
        static $DNS_INIT = false;
        static $DNS_HAS = false;//是否拥有DNS信息
        static $DNS_LEV = 0;//DNS的等级信息，1,2,3分别对应mode,ctl,act
        static $DNS_MOD = '';//DNS的model部分
        static $DNS_CTL = '';//Dns的controller部分
        static $DNS_ACT = '';//DNS的action的部分信息
        static $AUTOLOAD_FILE_LIST = array();//加载的文件表信息
        static $AUTOLOAD_ROUTE_LIST = array();//自动加载的路由表


        /**
         * 标准驼峰写法，首字母大写中间的大写字母转换为_加小写的方式
         * @param $code
         * @return string
         * User kuoqi
         * Datetime 2022/3/6 0006 10:35
         * Remark
         */
        static public function code2hump($code){
            //首先第一步，将首字母大写
            $arr = explode('_',$code);
            foreach($arr as $k=>$v){
                $arr[$k] = ucfirst($v);
            }
            $code = implode('',$arr);
            return $code;
        }

        /**
         * 将驼峰的方式转换为代码的方式 首字母大写中间的大写字母转换为_加小写的方式
         * @param $hump
         * @return string
         * User kuoqi
         * Datetime 2022/2/28 15:58
         * Remark
         */
        static public function hump2code($hump){
            $opt = '';
            for($i=0;$i<strlen($hump);$i++){
                if((($ascii = ord($hump[$i]))>=65)&&($ascii<=90)){
                    $opt .= $opt?('_'.chr($ascii+32)):chr($ascii+32);
                }else{
                    $opt .= $hump[$i];
                }
            }
            return $opt;
        }

        /**
         * 路由转路径信息
         * @param $route
         * @return string
         * User kuoqi
         * Datetime 2022/2/26 21:37
         * Remark
         */
        static public function route2path($route,$isArr = false){
            $arr = explode(Params::$RL,($route));
            $rs = array(
                'fname'=>'',//文件名
                'fcode'=> '',//唯一识别code
                'route'=>$route,//唯一路由信息
            );
            if(count($arr)>1){
                //字段信息大于1
                //最后一个字段出栈
                $lcode = array_pop($arr);
                foreach ($arr as $k=>$v){
                    $arr[$k] = self::hump2code($v);
                }
                $rs['fcode'] = $arr[0];
                unset($arr[0]);
                $code =($arr?( Params::$DS.implode(Params::$DS,$arr)):'');
                if($rs['fcode'] == 'kuoqi'){
                    $rs['fname'] = '/library'.$code.'/'. ucwords($lcode).'.class.php';
                }else if($rs['fcode'] == 'app'){
                    $rs['fname'] = '/'.Params::$APP_PATH.$code.'/'. ucwords($lcode).'.class.php';
                }else{
                    $rs['fname'] = '/extends/'.$rs['fcode'].$code.'/'. ucwords($lcode).'.php';
                }
            }else{
                //字段信息不大于1
                new Error('字段信息不大于1');
            }
            return $isArr?$rs:$rs['fname'];
        }

        /**
         * url参数模块字符串转数组
         * @param $stream
         * @return array
         */
        static public function urlparam2arr($stream){
            $lis = explode('&',$stream);
            $params = array();
            foreach ($lis as $item){
                $tmp = explode('=',$item);
                if(count($tmp)==2){
                    $params[$tmp[0]] = $tmp[1];
                }
            }
            return $params;
        }

        /**
         * 根据字符串转换为路径信息,{@ROOT}/library/api/php-excel/PHPExcel.php
         * @param $root
         * @return mixed
         * User kuoqi
         * Datetime 2022/3/30 10:48
         * Remark
         */
        static public function str2rootpath($root){
            $root = str_replace('{@ROOT}',Config::get('ROOT'),$root);
            $root = str_replace('{@APP}',Config::get('APP_ROOT'),$root);
            $root = str_replace('{@WEB}',Config::get('HOME'),$root);
            $root = str_replace('{@HOME}',Config::get('HOME'),$root);
            $root = str_replace(Params::$LL,Params::$DS,$root);
            return $root;
        }


        /**
         * @var string
         * User kuoqi
         * Datetime 2022/2/26 23:59
         * Remark 路由的请求方式
         */
        public $method = '';

        /**
         * @var string
         * User kuoqi
         * Datetime 2022/2/27 0:04
         * Remark 路由的路由信息
         */
        public $route = '';

        /**
         * @var array
         * User kuoqi
         * Datetime 2022/2/27 0:04
         * Remark 路由的参数信息
         */
        public $params = array();

        /**
         * @var string
         * User kuoqi
         * Datetime 2022/2/27 0:06
         * Remark 路由三要素 模型层
         */
        public $m = '';
        /**
         * @var string
         * User kuoqi
         * Datetime 2022/2/27 0:06
         * Remark 路由三要素-控制器层
         */
        public $c = '';
        /**
         * @var string
         * User kuoqi
         * Datetime 2022/2/27 0:06
         * Remark 路由三要素-动作层
         */
        public $a = '';

        /**
         * 除去mca其它的路由部分参数
         * @var array
         */
        public $extArray = array();

        //存储临时数据的对象信息
        private $tmp = array();

        /**
         * 路由初始化
         * Route constructor.
         * @param string $route 路由地址，没有的话置空即可
         * @param array $params 额外绑定的参数信息
         */
        public function __construct($route = '',$params = array())
        {
            //初始化路由的请求方式
            $this->method = strtoupper(Params::$METHOD);
            $this->route = str_replace(Params::$LL,Params::$RL,$route);//绑定路由信息
            $this->params = $params;//绑定额外参数信息
        }

        /**
         * 设置路由字符串
         * @param $route_string 路由字符串
         * @return $this 当前路由对象
         * User kuoqi
         * Datetime 2022/2/27 9:32
         * Remark
         */
        public function setRoute($route_string){
            new Error('等待废弃Kuoqi：：setRoute');
            $this->route = $route_string;
            return $this;
        }
        /**
         * 初始化dns的模块相关信息
         * User kuoqi
         * Datetime 2022/4/27 17:22
         * Remark
         */
        final function initDns(){
            if(!self::$DNS_INIT){
                $dns = Config::get('DNS_LIST');
                if(Config::get('DNS_STATUS')&&isset($dns[Params::$HOST])&&($dnsitem =$dns[Params::$HOST])){
                    if(isset($dnsitem['m'])){
                        self::$DNS_MOD = $dnsitem['m'];
                        self::$DNS_LEV++;
                    }
                    if(isset($dnsitem['c'])){
                        self::$DNS_CTL = $dnsitem['c'];
                        self::$DNS_LEV++;
                    }
                    if(isset($dnsitem['a'])){
                        self::$DNS_ACT = $dnsitem['a'];
                        self::$DNS_LEV++;
                    }
                    self::$DNS_HAS = true;
                }else{
                    self::$DNS_HAS = false;
                }
                self::$DNS_INIT = true;
            }
        }
        /**
         * 解析路由字符串为内部信息，本方法会将输入的数据无差别解析
         * User kuoqi
         * Datetime 2022/2/27 9:33
         * Remark
         */
        public function exec(){
            $this->tmp = array();
            $this->tmp['input'] = $this->route;//写入初始化的时候的路由信息
            if($this->tmp['input']){
                $this->tmp['ipt_arr'] = explode(Params::$RL,$this->route);//将字段分割为单个的参数信息
            }else{
                $this->tmp['ipt_arr'] = array();//将字段分割为单个的参数信息
            }
            $this->tmp['count'] = count($this->tmp['ipt_arr']);//获取当前的路由的字段数量
            $this->initDns();//尝试解析dns的相关信息
            //$this->tmp['order'] = 0;//0：逆序，1：顺序
            if(($this->tmp['count']==0)||$this->tmp['ipt_arr'][0]){
                $this->tmp['dm'] = (\Kuoqi::$app&&\Kuoqi::$app->route)?\Kuoqi::$app->route->m:Config::get('DEFAULT_MOD');//默认的m
                $this->tmp['dc'] = (\Kuoqi::$app&&\Kuoqi::$app->route)?\Kuoqi::$app->route->c:Config::get('DEFAULT_CTL');//默认的c
                $this->tmp['da'] = (\Kuoqi::$app&&\Kuoqi::$app->route)?\Kuoqi::$app->route->a:Config::get('DEFAULT_ACT');//默认的a
                $this->tmp['order'] = 0;//0：逆序，1：顺序
                //标识当前路由为相对路由
            }else{
                $this->tmp['dm'] = Config::get('DEFAULT_MOD');//默认的m
                $this->tmp['dc'] = Config::get('DEFAULT_CTL');//默认的c
                $this->tmp['da'] = Config::get('DEFAULT_ACT');//默认的a
                $this->tmp['order'] = 1;
            }
            //这里处理路由相关信息
            if(self::$DNS_HAS && self::$DNS_LEV){
                if(self::$DNS_LEV==1){
                    $this->execWithDnsLev1();
                }else if(self::$DNS_LEV==2){
                    throw new Error('系统不支持【DNS_LEV2的模式，请更换】');
                }else if(self::$DNS_LEV==3){
                    throw new Error('系统不支持【DNS_LEV3的模式，请更换】');
                }else{
                    throw new Error('系统不支持的路由模式');
                }
            }else{
                //这是没有路由绑定的时候的数据通道
                //这种情况就是硬抗
                $this->execWithNodns();
            }
            $this->m = Route::code2hump($this->params['m']);
            $this->c = Route::code2hump($this->params['c']);
            $this->a = Route::code2hump($this->params['a']);
            $this->tmp = array();
            //做完这个操作之后会自动将route完善成完整的路由信息
        }
        /**
         * 初始化 level 1 的方式
         * User kuoqi
         * Datetime 2022/4/27 18:42
         * Remark
         */
        private function execWithDnsLev1(){
            if($this->tmp['order']){
                //顺序
                $this->execWithDnsLev1Widthlr();
            }else{
                //逆序
                $this->execWithDnsLev1Widthrl();
            }
        }
        /**
         * 顺序 DNS为等级1的顺序路由处理
         * User kuoqi
         * Datetime 2022/4/28 9:56
         * Remark
         */
        private function execWithDnsLev1Widthlr(){
            $this->params['m'] = self::$DNS_MOD;
            //判定路由参数为几
            if($this->tmp['count']==2){
                $this->tmp['ipt_arr']['1']||($this->tmp['ipt_arr']['1'] = $this->tmp['dc']);
                $this->params['c'] = isset($this->params['c'])?$this->params['c']:$this->tmp['ipt_arr']['1'];
                $this->params['a'] = isset($this->params['a'])?$this->params['a']:$this->tmp['da'];
            }else if($this->tmp['count']==3){
                $this->tmp['ipt_arr']['1']||($this->tmp['ipt_arr']['1'] = $this->tmp['dc']);
                $this->tmp['ipt_arr']['2']||($this->tmp['ipt_arr']['2'] = $this->tmp['da']);
                $this->params['c'] = isset($this->params['c'])?$this->params['c']:$this->tmp['ipt_arr']['1'];
                $this->params['a'] = isset($this->params['a'])?$this->params['a']:$this->tmp['ipt_arr']['2'];
            }else if($this->tmp['count']>3){
                $this->tmp['ipt_arr']['1']||($this->tmp['ipt_arr']['1'] = $this->tmp['dc']);
                $this->tmp['ipt_arr']['2']||($this->tmp['ipt_arr']['2'] = $this->tmp['da']);
                $this->params['c'] = isset($this->params['c'])?$this->params['c']:$this->tmp['ipt_arr']['1'];
                $this->params['a'] = isset($this->params['a'])?$this->params['a']:$this->tmp['ipt_arr']['2'];
                //多余的路由转换为参数
                foreach($this->tmp['ipt_arr'] as $k=>$v){
                    if(($k<3)||in_array($v,array('m','c','a'))){ continue;}
                    if($k%2){
                        $this->params[$v] = isset($this->tmp['ipt_arr'][$k+1])?$this->tmp['ipt_arr'][$k+1]:'';
                    }
                    $this->extArray[] = $v;//额外参数获取
                }
            }else{
                throw new Error('异常');
            }
        }
        /**
         * 顺序 DNS为等级1的逆序路由处理
         * @throws Exception
         * User kuoqi
         * Datetime 2022/4/28 13:38
         * Remark
         */
        private function execWithDnsLev1Widthrl(){
            $this->params['m'] = self::$DNS_MOD;
            //判定路由参数为几
            //逆序-没有路由信息
            if($this->tmp['count']==0){
                isset($this->params['c'])||($this->params['c'] = $this->tmp['dc']);
                isset($this->params['a'])||($this->params['a'] = $this->tmp['da']);
            }else if($this->tmp['count']==1){
                isset($this->params['c'])||($this->params['c'] = $this->tmp['dc']);
                if(!isset($this->params['a'])){ $this->params['a'] = $this->tmp['ipt_arr'][0]?$this->tmp['ipt_arr'][0]:$this->tmp['da'];}
            }else if($this->tmp['count']==2){
                if(!isset($this->params['c'])){ $this->params['c'] = $this->tmp['ipt_arr'][0]?$this->tmp['ipt_arr'][0]:$this->tmp['dc'];}
                if(!isset($this->params['a'])){ $this->params['a'] = $this->tmp['ipt_arr'][1]?$this->tmp['ipt_arr'][1]:$this->tmp['da'];}
            }else{
                if(!isset($this->params['c'])){ $this->params['c'] = $this->tmp['ipt_arr'][0]?$this->tmp['ipt_arr'][0]:$this->tmp['dc'];}
                if(!isset($this->params['a'])){ $this->params['a'] = $this->tmp['ipt_arr'][1]?$this->tmp['ipt_arr'][1]:$this->tmp['da'];}
                foreach($this->tmp['ipt_arr'] as $k=>$v){
                    if($k<2){ continue;}
                    if(!(($k%2)||in_array($v,array('m','c','a')))){
                        $this->params[$v] = isset($this->tmp['ipt_arr'][$k+1])?$this->tmp['ipt_arr'][$k+1]:'';
                    }
                    $this->extArray[] = $v;//额外参数获取
                }
            }
        }
        /**
         * 初始化-顺序-没有dns
         * User kuoqi
         * Datetime 2022/4/28 11:25
         * Remark
         */
        private function execWithNodns(){
            if($this->tmp['order']){
                //顺序
                foreach($this->tmp['ipt_arr'] as $k=>$v){
                    if($k==0){ continue;}
                    if($k==1){
                        if(!isset($this->params['m'])){ $this->params['m'] = $v?$v:$this->tmp['dm'];}
                        continue;
                    }
                    if($k==2){
                        if(!isset($this->params['c'])){ $this->params['c'] = $v?$v:$this->tmp['dc'];}
                        continue;
                    }
                    if($k==3){
                        if(!isset($this->params['a'])){ $this->params['a'] = $v?$v:$this->tmp['da'];}
                        continue;
                    }
                    if(!(($k%2)||in_array($v,array('m','c','a')))){
                        $this->params[$v] = isset($this->tmp['ipt_arr'][$k+1])?$this->tmp['ipt_arr'][$k+1]:'';
                    }
                    $this->extArray[] = $v;//额外参数获取
                }
                isset($this->params['m'])||($this->params['m'] = $this->tmp['dm']);
                isset($this->params['c'])||($this->params['c'] = $this->tmp['dc']);
                isset($this->params['a'])||($this->params['a'] = $this->tmp['da']);
            }else{
                //逆序-没有路由信息
                if($this->tmp['count']==0){
                    isset($this->params['m'])||($this->params['m'] = $this->tmp['dm']);
                    isset($this->params['c'])||($this->params['c'] = $this->tmp['dc']);
                    isset($this->params['a'])||($this->params['a'] = $this->tmp['da']);
                }else if($this->tmp['count']==1){
                    isset($this->params['m'])||($this->params['m'] = $this->tmp['dm']);
                    isset($this->params['c'])||($this->params['c'] = $this->tmp['dc']);
                    if(!isset($this->params['a'])){ $this->params['a'] = $this->tmp['ipt_arr'][0]?$this->tmp['ipt_arr'][0]:$this->tmp['da'];}
                }else if($this->tmp['count']==2){
                    isset($this->params['m'])||($this->params['m'] = $this->tmp['dm']);
                    if(!isset($this->params['c'])){ $this->params['c'] = $this->tmp['ipt_arr'][0]?$this->tmp['ipt_arr'][0]:$this->tmp['dc'];}
                    if(!isset($this->params['a'])){ $this->params['a'] = $this->tmp['ipt_arr'][1]?$this->tmp['ipt_arr'][1]:$this->tmp['da'];}
                }else if($this->tmp['count']==3){
                    if(!isset($this->params['m'])){ $this->params['m'] = $this->tmp['ipt_arr'][0]?$this->tmp['ipt_arr'][0]:$this->tmp['dm'];}
                    if(!isset($this->params['c'])){ $this->params['c'] = $this->tmp['ipt_arr'][1]?$this->tmp['ipt_arr'][1]:$this->tmp['dc'];}
                    if(!isset($this->params['a'])){ $this->params['a'] = $this->tmp['ipt_arr'][2]?$this->tmp['ipt_arr'][2]:$this->tmp['da'];}
                }else{
                    if(!isset($this->params['m'])){ $this->params['m'] = $this->tmp['ipt_arr'][0]?$this->tmp['ipt_arr'][0]:$this->tmp['dm'];}
                    if(!isset($this->params['c'])){ $this->params['c'] = $this->tmp['ipt_arr'][1]?$this->tmp['ipt_arr'][1]:$this->tmp['dc'];}
                    if(!isset($this->params['a'])){ $this->params['a'] = $this->tmp['ipt_arr'][2]?$this->tmp['ipt_arr'][2]:$this->tmp['da'];}
                    foreach($this->tmp['ipt_arr'] as $k=>$v){
                        if(($k<3)||in_array($v,array('m','c','a'))){ continue;}
                        if($k%2){
                            $this->params[$v] = isset($this->tmp['ipt_arr'][$k+1])?$this->tmp['ipt_arr'][$k+1]:'';
                        }
                        $this->extArray[] = $v;//额外参数获取
                    }
                }
            }
        }

        /**
         * 返回当前根路由
         * @return string
         * @throws Error
         */
        public function flushRoot(){
            $this->exec();//对当前路由进行解析
            if(!self::$DNS_INIT){ $this->initDns();}
            if(self::$DNS_HAS&&(self::$DNS_LEV==1)){
                $route = Params::$RL . $this->c . Params::$RL . $this->a;
            }else{
                $route = Params::$RL . $this->m . Params::$RL . $this->c . Params::$RL . $this->a;
            }
            return $route;
        }

        /**
         * 显示当前完整路由
         * vbase
         * @return string
         * @throws Error
         */
        public function flushComplete(){
            $this->exec();//对当前路由进行解析
            if(!self::$DNS_INIT){ $this->initDns();}
            if(self::$DNS_HAS&&(self::$DNS_LEV==1)){
                $route = Params::$RL . $this->c . Params::$RL . $this->a;
                foreach ($this->params as $k=>$v){
                    if(in_array($k,array('m','c','a'))){ continue;}
                    $route .= Params::$RL . $k . ($v?(Params::$RL .$v):'');
                }
            }else{
                $route = Params::$RL . $this->m . Params::$RL . $this->c . Params::$RL . $this->a;
                foreach ($this->params as $k=>$v){
                    if(in_array($k,array('m','c','a'))){ continue;}
                    $route = $route . Params::$RL . $k . ($v?(Params::$RL .$v):'');
                }
            }
            return $route;
        }

        /**
         * 返回模板文件,不携带后缀的那种即可,文件路径为DS
         * @return string
         * @throws Error
         */
        public function flushView(){
            $this->exec();//对当前路由进行解析
            if(!self::$DNS_INIT){ $this->initDns();}
            $route = '/'.Params::$APP_PATH
                .'/'.self::hump2code($this->m)
                .'/'.'view'
                .'/'.self::hump2code($this->c)
                .'/'.self::hump2code($this->a);
            foreach ($this->params as $k=>$v){
                if(in_array($k,array('m','c','a'))){ continue;}
                $route = $route .'/'. self::hump2code($k) . ($v?('/' . self::hump2code($v)):'');
            }
            return $route;
        }
    }

    /**
     * 日志模块的相关数据记录
     * Class Logs
     * @package Kuoqi
     */
    class Logs{
        /**
         * 临时的数据监听
         * @var array
         */
        static $tmp_listen = array();

        //是否开启
        /**
         * 切片文件的大小
         * @var string
         */
        protected $file_size = '2097152';//2M = 2097152
        //当前的日志头
        protected $file_prefix = '';

        /**
         * 是否cli模式
         * @var bool
         */
        protected $iscli = false;
        /**
         * 使用日志模块，默认为info的文件信息
         * Logs constructor.
         * @param string $filename
         */
        public function __construct($filename = 'info')
        {
            if(strtolower(PHP_SAPI)=='cli'){
                $this->iscli = true;
            }else{
                $this->iscli = false;
            }
            $this->file_prefix = $filename.'_';
            //监听开始
            $this->iscli||self::listenStart('request');
        }

        //记录一条日志数据信息
        public function log($msg,$code = 'info',$timelen = 0){
            if($this->iscli){
                //这种模式下面，只有直接写入日志发的份
                $stream = sprintf('[%s]'.date('Y-m-d H:i:s').' %s runtime %s'.PHP_EOL
                    ,$code
                    ,$msg
                    ,$timelen
                );
                $fopen = $this->fopen();
                fwrite($fopen,$stream);
                fclose($fopen);
            }else{
                Params::$LOG_DATA[] = self::initItem($msg,$code,$timelen);
            }

        }

        public function fopen(){
            $root = Route::str2rootpath(Params::$LOG_ROOT);
            if(!(is_dir($root)||mkdir($root,'0777',true))){
                die('log model:make '.Params::$LOG_ROOT.' error'.PHP_EOL);//如果创建失败，则直接进入到异常流程
            }
            //将内容写入到日志里面去
            $file = $root.'/'.$this->file_prefix.date('Ymd',time()).'.log';
            if(is_file($file)&&(filesize($file)>$this->file_size)){
                //进行文件转存
                $tfile = $root.'/'.$this->file_prefix.date('Ymd',time()).'_'.date('His').'.log';
                file_put_contents($tfile,file_get_contents($file));
                $fopen = fopen($file,'w');
            }else{
                $fopen = fopen($file,'a');
            }
            if(!$fopen){
                die('log model:make '.$fopen.' error'.PHP_EOL);
            }
            return $fopen;
        }

        public function __destruct()
        {
            if($this->iscli){ return;}
            $fopen = $this->fopen();
            fwrite($fopen,$this->getHead());
            fwrite($fopen,$this->getConts());
            fwrite($fopen,$this->getFoot());
            fclose($fopen);
        }

        /**
         * 获取每条日志的头部信息
         */
        final function getHead(){
            return sprintf('[request]%s on %s ips %s'.PHP_EOL
                ,Params::$METHOD
                ,isset($_SERVER['REQUEST_URI'])?$_SERVER['REQUEST_URI']:'(noset)'
                ,isset($_SERVER["REMOTE_ADDR"])?$_SERVER["REMOTE_ADDR"]:'(noset)'
            );
        }
        final function getConts(){
            $stream = '';
            foreach (Params::$LOG_DATA as $item){
                $stream .= sprintf('[%s]'.date('Y-m-d H:i:s').' %s at %s runtime %s'.PHP_EOL
                    ,$item['code']
                    ,$item['msg']
                    ,$item['time']
                    ,$item['timelen']
                    );
            }
            return $stream;
        }

        /**
         * 获取尾部相关信息
         */
        final function getFoot(){
            return sprintf('[request-end] at %s runtime %s'.PHP_EOL
                ,date('Y-m-d H:i:s'),
                self::listenEnd('request')
            );
        }

        //获取当前的唯一识别数组信息
        static public function initItem($msg,$code,$timelen = 0){
            return array('msg'=>$msg,'code'=>$code,'timelen'=>$timelen,'time'=>date('Y-m-d H:i:s'));
        }

        //创建一个时间监测点
        static public function listenStart($code = 'normal'){
            self::$tmp_listen[$code] = microtime(true);
        }
        //结束一个时间监测点
        static public function listenEnd($code = 'normal'){
            if(isset(self::$tmp_listen[$code])){
                $code = microtime(true) - self::$tmp_listen[$code];
                unset(self::$tmp_listen[$code]);
                return $code;
            }else{
                return 'error';
            }
        }
    }
}

/*
 * 基础工厂对象
 */
namespace {
    use Kuoqi\Error;
    use Kuoqi\Params;
    use Kuoqi\Config;
    use Kuoqi\Route;
    /**
     * Class Kuoqi
     * User kuoqi
     * Datetime 2022/2/26 11:14
     * Remark 工厂信息
     */
    class Kuoqi {
        /**
         * @var null
         * User kuoqi
         * Datetime 2022/2/27 10:25
         * Remark 当前应用的app包
         */
        static $app = null;

        /**
         * 日志模块
         * vbase
         * @var null
         */
        static $logs = null;

        /**
         * 系统初始化的核心模块
         * vbase
         * @param array $opts
         * @return \Kuoqi\App|\Kuoqi\Core
         */
        static public function __initialize($opts = array()){
            Error::process('系统初始化');
            Params::__initialize();//参数模块初始化
            Config::__initialize(isset($opts['config'])?$opts['config']:array());//参数模块初始化
            spl_autoload_register(array('Kuoqi','__autoload'));//注册自动加载函数信息
            //判定模式，确定使用cli模式还是web模式
            //返回app的相关模块信息
            if(Params::$PHP_MODE == Params::$CODE_MODE_WEB){
                //进入web核心
                //注册常规异常加载项
                //这个会跳过系统自身的异常处理，所有...
                //set_error_handler(array('Kuoqi','error_handler'));
                //throw new ....进入这个流程
                //针对哪些没有try的给它一个立即去世的机会
                set_exception_handler(array('Kuoqi','exception_handler'));
                Error::process('系统初始化成功');
                self::$logs = new \Kuoqi\Logs('info');
                return self::$app =  new \Kuoqi\App();
            }else{
                //使用cli核心,进入cli核心
                return self::$app = new \Kuoqi\Cli();
            }
        }

        /**
         * 使用某个对象作为app对象
         * vbase
         * @param $app
         * @throws Error
         */
        static public function useApp($app){
            //self::$app = $app;
            Error::process('应用输入系统');
            //这里执行一些app的方法，给APP安排上在这上面的显示和初始化这些
            $behavior = new \Kuoqi\Behavior($app);
            $behavior->exec();//行为的解析，使用多一个函数的目的是让这个信息可以被手动变更，而不是直接一次性固定死了
            //todo--初始化app对象的安排
            //这里需要做些其他操作的话，就放到这里吧


        }

        /**
         * 注册的自动加载类数据信息
         * @param $route
         * @return \Kuoqi\Exception
         * @throws Exception
         */
        static public function __autoload($route){
            Route::$AUTOLOAD_ROUTE_LIST[] = $route;
            $path = Route::route2path($route,true);
            //根据路径信息加载文件
            if($path['fcode']=='kuoqi'){ $funame = '{@ROOT}'.$path['fname']; }else{ $funame = '{@APP}'.$path['fname']; }
            Route::$AUTOLOAD_FILE_LIST[] = $funame;
            $funame = Route::str2rootpath($funame);
            if(!(is_file($funame)&&is_readable($funame))){
                return new Error($funame.' not is_file or is_readable');
            }
            include_once $funame;
            if(class_exists($path['route'])){
                if(method_exists($path['route'],'__initialize')){
                    eval('$path["route"]::__initialize();');
                }
            }elseif(interface_exists($path['route'])){}
            else{
                throw new Error('Class['.$path['route'].'] Non-existent');
            }
        }

        /**
         * 接管php系统异常
         * @param $errno
         * @param $errstr
         * @param $errfile
         * @param $errline
         * @return Error
         */
        static public function error_handler($errno,$errstr,$errfile,$errline){
            die('这个是什么，需要重新开发,kuoqi.php code ssdsdasdsdsds');
            //接管系统异常
            $error = new Error($errstr,false);
            $error->setFile($errfile);
            $error->setCode($errno);
            $error->setLine($errline);
            return $error->quit();//立即去世
        }

        /**
         * User kuoqi
         * Datetime 2022/3/1 15:15
         * Remark throw new ....进入这个流程
         */
        static public function exception_handler($error){
            $exception = new Error($error->getMessage());
            $exception->setLine($error->getLine());
            $exception->setCode($error->getCode());
            $exception->setFile($error->getFile());
            $exception->setTraceStream($error->getTraceAsString ());
            $error = $exception;
            return $error->quit();//立即去世
        }

        //增加一个日志
        static public function log($msg,$code = 'info',$timelet = 0){
            if(!self::$logs){return false; }//日志模块不存在的情况不配记录日志
            self::$logs->log($msg,$code,$timelet);//记录一个日志信息
        }
    }
}